package com.ofps.flow.service.impl;

import java.util.*;
import java.util.logging.Handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ofps.common.core.domain.entity.SysDept;
import com.ofps.common.core.domain.entity.SysUser;
import com.ofps.common.exception.ServiceException;
import com.ofps.common.utils.StringUtils;
import com.ofps.flow.domain.Dto.FlowInfoInstDto;
import com.ofps.flow.domain.Dto.FlowNodeDto;
import com.ofps.flow.domain.Dto.FlowNodeInstDto;
import com.ofps.flow.domain.EnterFlowInfo;
import com.ofps.flow.domain.EnterFlowNode;
import com.ofps.flow.domain.EnterFlowNodeInst;
import com.ofps.flow.mapper.EnterFlowInfoMapper;
import com.ofps.flow.mapper.EnterFlowNodeInstMapper;
import com.ofps.flow.mapper.EnterFlowNodeMapper;
import com.ofps.forms.common.utils.R;
import com.ofps.forms.domain.AnswerBlank;
import com.ofps.forms.domain.AnswerCheckbox;
import com.ofps.forms.domain.AnswerRadio;
import com.ofps.forms.mapper.AnswerBlankMapper;
import com.ofps.forms.mapper.AnswerCheckboxMapper;
import com.ofps.forms.mapper.AnswerRadioMapper;
import com.ofps.system.mapper.SysDeptMapper;
import com.ofps.system.mapper.SysUserMapper;
import org.apache.shiro.crypto.hash.Hash;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.ofps.flow.mapper.EnterFlowInfoInstMapper;
import com.ofps.flow.domain.EnterFlowInfoInst;
import com.ofps.flow.service.IEnterFlowInfoInstService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 流程实例Service业务层处理
 *
 * @author ofps
 * @date 2022-06-01
 */
@Service
public class EnterFlowInfoInstServiceImpl extends ServiceImpl<EnterFlowInfoInstMapper, EnterFlowInfoInst> implements IEnterFlowInfoInstService {

    @Resource
    private EnterFlowInfoInstMapper enterFlowInfoInstMapper;
    @Resource
    private EnterFlowInfoMapper enterFlowInfoMapper;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private EnterFlowNodeInstMapper enterFlowNodeInstMapper;
    @Resource
    private EnterFlowNodeMapper enterFlowNodeMapper;


    //答案
    @Resource
    private AnswerBlankMapper answerBlankMapper;
    @Resource
    private AnswerRadioMapper answerRadioMapper;
    @Resource
    private AnswerCheckboxMapper answerCheckboxMapper;


    /**
     * 查询流程实例列表
     *
     * @param enterFlowInfoInst 流程实例
     * @return 流程实例
     */
    @Override
    public List<EnterFlowInfoInst> selectEnterFlowInfoInstList(EnterFlowInfoInst enterFlowInfoInst) {
        return baseMapper.selectEnterFlowInfoInstList(enterFlowInfoInst);
    }

    @Override
    public R queryByUserId(FlowInfoInstDto params) {
        //
        QueryWrapper<EnterFlowInfoInst> queryWrapper =
                new QueryWrapper<EnterFlowInfoInst>()
                        .eq(StringUtils.isNotNull(params.getUserId()), "user_id", params.getUserId())
                        .eq(StringUtils.isNotNull(params.getCurrentUserId()), "current_user_id", params.getCurrentUserId())
                        .like(StringUtils.isNotNull(params.getFlowName()), "name", params.getFlowName())
                        .eq(StringUtils.isNotNull(params.getStatus()), "status", params.getStatus())
                        .apply(params.getDateRange() != null && StringUtils.isNotNull(params.getDateRange().get("beginTime")),
                                "date_format (create_time,'%Y-%m-%d') >= date_format('" + params.getDateRange().get("beginTime") + "','%Y-%m-%d')")
                        .apply(params.getDateRange() != null && StringUtils.isNotNull(params.getDateRange().get("endTime")),
                                "date_format (create_time,'%Y-%m-%d') <= date_format('" + params.getDateRange().get("endTime") + "','%Y-%m-%d')");

        //查询
        Page<EnterFlowInfoInst> flowInfoInstPage = enterFlowInfoInstMapper.selectPage(
                new Page<>(params.getPageNo(), params.getPageSize()), queryWrapper);
        //总数
        Long counts = enterFlowInfoInstMapper.selectCount(queryWrapper);


        if (flowInfoInstPage == null) return R.error("暂无数据");

        List<Map<String, Object>> res = new LinkedList<>();
        //返回包装
        List<EnterFlowInfoInst> flowInsts = flowInfoInstPage.getRecords();
        for (EnterFlowInfoInst flow : flowInsts) {
            Long userId = flow.getUserId();
            SysUser sysUser = sysUserMapper.selectUserById(userId);
            String userName = sysUser.getUserName();
            String nickName = sysUser.getNickName();
            SysDept dept = sysUser.getDept();
            String deptName = dept.getDeptName();
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("flowInst", flow);
            hashMap.put("userName", userName);
            hashMap.put("nickName", nickName);
            hashMap.put("deptName", deptName);
            res.add(hashMap);
        }
        return R.ok("查询成功").put("counts", counts).put("flowInfoInst", res);
    }

    /**
     * 获取我的申请-详情数据
     *
     * @param jsonObject 请求参数
     * @return 我的申请-详情数据
     */
    @Override
    public JSONObject findInstDetail(JSONObject jsonObject) {
        JSONObject dataJson = new JSONObject();
        String flowInstId = jsonObject.getString("flowInstId");
        EnterFlowInfoInst enterFlowInfoInst = new EnterFlowInfoInst();
        enterFlowInfoInst.setId(flowInstId);
        List<EnterFlowInfoInst> enterFlowInfoInsts = enterFlowInfoInstMapper.selectList(new QueryWrapper<>(enterFlowInfoInst));
        dataJson.put("flowInst", null);
        dataJson.put("flowNodeInst", null);
        if (enterFlowInfoInsts != null && enterFlowInfoInsts.size() > 0) {
            EnterFlowInfoInst infoInst = enterFlowInfoInsts.get(0);
            String infoInstId = infoInst.getId();
            EnterFlowNodeInst enterFlowNodeInst = new EnterFlowNodeInst();
            enterFlowNodeInst.setFlowInstId(infoInstId);
            QueryWrapper<EnterFlowNodeInst> wrapper = new QueryWrapper<>();
            wrapper.eq("flow_inst_id", infoInstId);
            wrapper.orderByAsc("order_id");
            List<EnterFlowNodeInst> nodeInsts = enterFlowNodeInstMapper.selectList(wrapper);
            List<FlowNodeInstDto> dtoList = new ArrayList<>();
            for (EnterFlowNodeInst nodeInst : nodeInsts) {
                FlowNodeInstDto dto = new FlowNodeInstDto();
                BeanUtils.copyProperties(nodeInst, dto);
                Long relatedUserId = nodeInst.getRelatedUserId();
                if (relatedUserId != null) {
                    SysUser sysUser = sysUserMapper.selectUserById(relatedUserId);
                    dto.setRelatedUserName(sysUser.getUserName());
                    dto.setRelatedUserNickName(sysUser.getNickName());
                    dtoList.add(dto);
                }
            }
            dataJson.put("flowInst", infoInst);
            dataJson.put("flowNodeInst", dtoList);
        }
        return dataJson;
    }

    /**
     * 获取流程模型接口
     *
     * @param jsonObject 请求参数
     * @return 流程模型数据
     */
    @Override
    public JSONObject getFlowInfoWithNode(JSONObject jsonObject) {
        JSONObject dataJson = new JSONObject();
        String flowId = jsonObject.getString("flowId");
        QueryWrapper<EnterFlowInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("id", flowId);
        List<EnterFlowInfo> enterFlowInfos = enterFlowInfoMapper.selectList(wrapper);
        dataJson.put("flowInfo", null);
        dataJson.put("flowNodes", null);
        if (enterFlowInfos != null && enterFlowInfos.size() > 0) {
            for (EnterFlowInfo info : enterFlowInfos) {
                dataJson.put("flowInfo", info);
                String id = info.getId();
                QueryWrapper<EnterFlowNode> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("flow_id", id);
                queryWrapper.orderByAsc("order_id");
                List<EnterFlowNode> enterFlowNodes = enterFlowNodeMapper.selectList(queryWrapper);
                List<FlowNodeDto> flowNodeDtoList = new ArrayList<>();
                // 处理昵称和用户名
                for (EnterFlowNode node : enterFlowNodes) {
                    FlowNodeDto dto = new FlowNodeDto();
                    BeanUtils.copyProperties(node, dto);
                    Long relatedUserId = dto.getRelatedUserId();
                    if (relatedUserId != null) {
                        SysUser sysUser = sysUserMapper.selectUserById(relatedUserId);
                        dto.setRelatedUserName(sysUser.getUserName());
                        dto.setRelatedUserNickName(sysUser.getNickName());
                        flowNodeDtoList.add(dto);
                    }
                }
                dataJson.put("flowNodes", flowNodeDtoList);
            }
        }
        return dataJson;
    }

    /**
     * 建立流程实例接口
     * @return 成功或失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertFlowInst(JSONObject jsonObject) {
        JSONObject flowInst = jsonObject.getJSONObject("flowInst");
        EnterFlowInfoInst enterFlowInfoInst = JSONObject.toJavaObject(flowInst, EnterFlowInfoInst.class);
        enterFlowInfoInst.setCreateTime(new Date());
        JSONArray flowNodeInst = jsonObject.getJSONArray("flowNodesInst");
        if (flowNodeInst == null || flowNodeInst.size() < 1) {
            throw new ServiceException("缺失子节点数据, 请检查~");
        }

        for (Object obj : flowNodeInst) {
            JSONObject object = JSONObject.parseObject(JSONObject.toJSONString(obj));
            EnterFlowNodeInst enterFlowNodeInst = JSON.toJavaObject(object, EnterFlowNodeInst.class);
            enterFlowNodeInst.setTime(new Date());
            enterFlowNodeInstMapper.insert(enterFlowNodeInst);
        }

        enterFlowInfoInstMapper.insert(enterFlowInfoInst);
    }

    /***
     * 查询答案表
     * @param questionType
     * @param flowInstId
     * @return
     */
    @Override
    public R queryAnswer(Integer questionType, String questionId, String flowInstId) {

        Object answer = new Object();
        switch (questionType) {
            //填空
            case 0:
                answer = answerBlankMapper.selectOne(new QueryWrapper<AnswerBlank>().eq("flow_inst_id", flowInstId).eq("question_id", questionId));
                break;
            //单选
            case 1:
                answer = answerRadioMapper.selectOne(new QueryWrapper<AnswerRadio>().eq("flow_inst_id", flowInstId).eq("question_id", questionId));
                break;
            //多选
            case 2:
                answer = answerCheckboxMapper.selectOne(new QueryWrapper<AnswerCheckbox>().eq("flow_inst_id", flowInstId).eq("question_id", questionId));
                break;
            default:
                break;
        }
        if (answer != null)
            return R.ok("查询成功").put("answer", answer);
        else
            return R.error("没有该答案");
    }

    @Override
    public R review(Integer op, EnterFlowInfoInst flowInst, EnterFlowNodeInst nodeInst) {
//        操作码
        //流程前进
        if (op == 0) {
            //根据flowInst的节点序号 和 流程id 查找 flowNodeInst表
            EnterFlowNodeInst nodeInstSelected = enterFlowNodeInstMapper.selectOne(new QueryWrapper<EnterFlowNodeInst>().eq("flow_inst_id", flowInst.getId()).eq("order_id", flowInst.getCurrentOrder()));
            //当前节点是否最后一个节点
            if (nodeInstSelected.getLast()) {
                //修改flow_inst表状态 status设置为1
                flowInst.setStatus(1L);
                enterFlowInfoInstMapper.updateById(flowInst);
                //修改节点表
                nodeInstSelected.setIdea(nodeInst.getIdea());
                nodeInstSelected.setSign(nodeInst.getSign());
                nodeInstSelected.setTime(nodeInst.getTime());
                nodeInstSelected.setIp(nodeInst.getIp());
                nodeInstSelected.setStatus(2L);
                enterFlowNodeInstMapper.updateById(nodeInstSelected);
            } else {
                //当前第一个节点  状态改为2 审核通过
                nodeInstSelected.setStatus(2L);
                nodeInstSelected.setIdea(nodeInst.getIdea());
                nodeInstSelected.setSign(nodeInst.getSign());
                nodeInstSelected.setTime(nodeInst.getTime());
                nodeInstSelected.setIp(nodeInst.getIp());
                nodeInstSelected.setStatus(2L);
                enterFlowNodeInstMapper.updateById(nodeInstSelected);
                //下一个节点
                EnterFlowNodeInst nodeInstNext = enterFlowNodeInstMapper.selectOne(new QueryWrapper<EnterFlowNodeInst>().eq("flow_inst_id", flowInst.getId()).eq("order_id", flowInst.getCurrentOrder() + 1L));
                nodeInstNext.setStatus(1L);
                enterFlowNodeInstMapper.updateById(nodeInstNext);
                //更新流程实例信息
                flowInst.setCurrentUserId(nodeInstNext.getRelatedUserId());
                flowInst.setCurrentOrder(nodeInstNext.getOrderId());
                enterFlowInfoInstMapper.updateById(flowInst);
            }
        }
        //流程终止
        else if (op == 2) {
            //根据flowInst的节点序号 和 流程id 查找 flowNodeInst表
            EnterFlowNodeInst nodeInstSelected = enterFlowNodeInstMapper.selectOne(new QueryWrapper<EnterFlowNodeInst>().eq("flow_inst_id", flowInst.getId()).eq("order_id", flowInst.getCurrentOrder()));
            //修改flow_inst表状态 status设置为2
            flowInst.setStatus(2L);
            enterFlowInfoInstMapper.updateById(flowInst);
            //修改节点表
            nodeInstSelected.setIdea(nodeInst.getIdea());
            nodeInstSelected.setSign(nodeInst.getSign());
            nodeInstSelected.setTime(nodeInst.getTime());
            nodeInstSelected.setIp(nodeInst.getIp());
            nodeInstSelected.setStatus(3L);
            enterFlowNodeInstMapper.updateById(nodeInstSelected);
        }
        //流程回退
        else if (op == 3) {
            //根据flowInst的节点序号 和 流程id 查找 flowNodeInst表
            List<EnterFlowNodeInst> flowNodeInstList = enterFlowNodeInstMapper.selectList(new QueryWrapper<EnterFlowNodeInst>().eq("flow_inst_id", flowInst.getId()).orderByAsc("order_id"));
            System.out.println(flowNodeInstList);
//            flowNodeInstList.sort(new Comparator<EnterFlowNodeInst>() {
//                @Override
//                public int compare(EnterFlowNodeInst o1, EnterFlowNodeInst o2) {
//                    return (int) (o1.getOrderId() - o2.getOrderId());
//                }
//            });
            Long currentOrderId = flowInst.getCurrentOrder();

            for (int i = 0; i < flowNodeInstList.size(); i++) {
                EnterFlowNodeInst node = flowNodeInstList.get(i);

                node.setStatus(i == currentOrderId - 1 ? 4L : 0L);
                if (i == 0) {
                    //修改流程实例
                    flowInst.setCurrentUserId(node.getRelatedUserId());
                    flowInst.setCurrentOrder(node.getOrderId());
                    flowInst.setStatus(3L);
                    enterFlowInfoInstMapper.updateById(flowInst);
                    node.setStatus(1L);
                }
                if (i == currentOrderId - 1) {
                    node.setTime(nodeInst.getTime());
                    node.setSign(nodeInst.getSign());
                    node.setIp(nodeInst.getIp());
                    node.setIdea(nodeInst.getIdea());
                }
                //更新节点
                enterFlowNodeInstMapper.updateById(node);

            }
        } else
            return R.error("操作码错误");

        return R.ok("当前审批成功！");
    }
}
